﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;

using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Web.Mvc;

namespace System.Web
{
    /// <summary>
    /// 上传成功,或移动图片成功委托
    /// </summary>
    public delegate void UploadSuccess(FileInfo info);
    /// <summary>
    /// 3.0 单个文件接收
    ///上传文件帮助类
    /// </summary>
    public partial class UploadOperate
    {
        /// <summary>
        /// 当前请求上线文
        /// </summary>
        private HttpContext _Context = HttpContext.Current;
        /// <summary>
        /// 当前上传 对象
        /// </summary>
        private HttpPostedFile _PostedFile = null;
        /// <summary>
        /// 当前上传的文件信息
        /// </summary>
        private UploadFileInfo _fileInfo = null;
        //上传文件扩展名 过滤
        private string[] extensionList = null;
        //文件最大大小,字节数据
        public int MinSize = 0;
        //文件最小大小，字节数5MB
        public int MaxSize = 61664480;
        /// <summary>
        /// 初始化
        /// </summary>
        public UploadOperate()
        {
            HttpRequest request = _Context.Request;
            if (request.Files.Count <= 0)
            {
                throw new HttpException(500, "服务器没有获取到上传的文件");
            }
            _PostedFile = request.Files[0];
            _fileInfo = new UploadFileInfo(_PostedFile);
        }
        /// <summary>
        /// 初始化 使用绝对目录
        /// </summary>
        public UploadOperate(string TempFile, string UploadFiles) : this()
        {
            _fileInfo.SetPath(TempFile, UploadFiles);
        }
        /// <summary>
        /// 上传图片的统一处理
        /// </summary>
        public void UploadAutoHandle(string subfolder, bool IsBack, UploadSuccess onSuccess = null)
        {
            this.MaxSize = ReqHelper.GetInt("maxsize", 1024);
            this.MinSize = ReqHelper.GetInt("minsize", 0);
            try
            {
                //判断是否需要后台，剪切图片
                string isClip = ReqHelper.GetString("isclip", "0");
                string filename = "";
                if (isClip == "0")//接收上传文件
                {
                    //简单上传文件
                    filename = this.Upload();
                }
                else if (isClip == "1")//图片后台剪切
                {
                    //获取 target的宽高
                    int targetWidth = ReqHelper.GetInt("targetwidth", 100);
                    int targetHeight = ReqHelper.GetInt("targetheight", 100);
                    filename = this.UploadWirthClip(targetWidth, targetWidth);
                }
                else if (isClip == "-1") //前台剪切或图片压缩
                {
                    //1.获取图片扩展名
                    string extentions = ReqHelper.GetString("extention");
                    //接收图片数据
                    filename = this.UploadImg(extentions);
                    //2.判断是否自动移动图片
                    bool automove = ReqHelper.GetBool("automove", false);
                    if (automove)
                    {
                        filename = Move(filename, subfolder, IsBack, onSuccess);
                    }
                }
                ReqHelper.ResponseText(this.GetSuccessStr(filename));
            }
            catch (Exception ex)
            {
                ReqHelper.ResponseText(this.GetErrorStr(ex.Message));
            }
        }

        #region 上传逻辑处理
        /// <summary>
        /// 保存之前验证
        /// </summary>
        private void CheckAbove()
        {
            //1.扩展名验证
            if (extensionList != null && extensionList.Any(q => q == _fileInfo.Extention) == false)
            {
                throw new Exception("目前仅支持上传，" + String.Join(",", extensionList) + ",格式的图片");
            }
            //2.文件大小验证
            if (_fileInfo.ContentLength < MinSize)
            {
                throw new Exception("上传文件太小,不能小于:" + new ByteHelper(MinSize).GetShow() );
            }
            else if (_fileInfo.ContentLength > MaxSize)
            {
                throw new Exception("上传的文件太大，不能超过：" + new ByteHelper(MaxSize).GetShow());
            }
        }
        /// <summary>
        /// 接收上传文件到临时文件夹,返回上传后的文件名
        /// </summary>
        /// <returns></returns>
        public string Upload()
        {
            CheckAbove();

            //判断是否重命名
            if (_fileInfo.IsRename)
            {
                //保存文件
                _PostedFile.SaveAs(_fileInfo.NewFullName_Temp);
                return _fileInfo.NewName;
            }
            //保存文件
            _PostedFile.SaveAs(_fileInfo.OldFullName_Temp);
            return _fileInfo.OldName;
        }
        /// <summary>
        /// 接收二进制上传的图片
        /// 默认：保存成png图片
        /// </summary>
        /// <returns></returns>
        public string UploadImg(string newExtention = ".png")
        {
            //保存之前验证
            CheckAbove();
            //接收图片文件
            HttpRequest req = _Context.Request;
            string newname = _fileInfo.CreateNewName(newExtention);
            //接收二级制数据并保存
            Stream stream = _PostedFile.InputStream;
            byte[] dataOne = new byte[stream.Length];
            stream.Read(dataOne, 0, dataOne.Length);
            FileStream fs = new FileStream(_fileInfo.TempFile + newname, FileMode.Create, FileAccess.Write);
            try
            {
                fs.Write(dataOne, 0, dataOne.Length);
            }
            finally
            {
                fs.Close();
            }
            return newname;
        }
        /// <summary>
        /// 接收 上传图片，产生新剪切图片
        /// 剪切描述：
        ///     1.根据图片的大小，先缩放，如果图片比例大于target 比例  以宽为标准缩放，并剪切
        ///     2.如果图片的比例小于target比例 以高为标准缩放并，剪切
        /// </summary>
        /// <returns>接收上传文件名|新产生的文件名</returns>
        public string UploadWirthClip(int targetWidth, int targetHeight, string newExtention = ".png")
        {
            //1.先接收新图片到临时文件夹
            string filename = Upload();
            string _TempFile = _fileInfo.TempFile;
            string filepath = _TempFile + filename;
            //2.缩放处理并生成新的图片
            //产生新的图片名称
            string targetname = Guid.NewGuid().ToString() + newExtention;
            Bitmap img = ImgHelper.ResizeCut(filepath, targetWidth, targetHeight);
            //保存成png图片
            img.Save(_TempFile + targetname, ImageFormat.Png);
            return filename + "|" + targetname;
        }
        #endregion

        #region 上传成功，将文件从临时文件夹中移动到规定文件夹
        /// <summary>
        /// 移动临时文件夹文件，到上传文件的子文件夹
        /// </summary>
        /// <param name="filename">文件名</param>
        /// <param name="subFolder">要移动的子文件夹</param>
        /// <returns>返回格式"subFolder/filename"</returns>
        public static string Move(string filename, string subFolder,bool IsBack=true, UploadSuccess onSuccess = null)
        {
            UploadFileInfo _fileInfo = new UploadFileInfo();
            if (filename.Contains("/"))
            {
                int index = filename.LastIndexOf("/")+1;
                filename = filename.Substring(index, filename.Length - index);
            }
            //1.判断文件是否在临时文件夹存在
            if (_fileInfo.ExitsFromTempFile(filename) == false)
            {
                throw new Exception("获取临时文件夹中的文件失败，您可以尝试重新上传");
            }
            //2.从临时文件夹中移动到上传文件夹的子文件夹
            string newFullName = _fileInfo.GetUploadFiles_Sub(subFolder,IsBack) + "\\" + filename;
            if (File.Exists(newFullName))
            {
                File.Delete(newFullName);
            }
            //3.移动文件
            File.Move(_fileInfo.TempFile + filename, newFullName);
            string resultfilename = subFolder + "/" + filename;
            //4.移动成功，委托处理
            if (onSuccess != null)
            {
                onSuccess(new FileInfo(newFullName));
            }
            //返回路径需要反斜杠
            return resultfilename;
        }
        ///// <summary>
        ///// 移动临时文件夹文件，到上传文件的子文件夹
        ///// 从当前上下文中获取子文件夹 （subfolder）
        ///// </summary>
        ///// <param name="filename">文件名</param>
        ///// <param name="onSuccess">移动成功事件</param>
        ///// <returns></returns>
        //public static string Move(string filename, UploadSuccess onSuccess = null)
        //{
        //    if (string.IsNullOrEmpty(filename))
        //        throw new HttpException(500, "移动上传文件时，传入filename为空");
        //    string subfolder = ReqHelper.GetString("subfolder");
        //    if (string.IsNullOrEmpty(subfolder))
        //    {
        //        subfolder = B_UserHelper.GetUserID().ToString();
        //    }
        //    return Move(filename, subfolder, true, onSuccess);
        //}
        //public static string Move_A(string filename, UploadSuccess onSuccess = null)
        //{
        //    if (string.IsNullOrEmpty(filename))
        //        throw new HttpException(500, "移动上传文件时，传入filename为空");
        //    string subfolder = ReqHelper.GetString("subfolder");
        //    if (string.IsNullOrEmpty(subfolder))
        //    {
        //        subfolder = A_UserHelper.GetUserID().ToString();
        //    }
        //    //设置前台保存地址

        //    return Move(filename, subfolder,false, onSuccess);
        //}
        /// <summary>
        /// 移动临时文件夹文件，到上传文件的子文件夹
        /// 从当前上下文中获取移动的文件名，以及存储的子文件夹
        /// </summary>
        /// <param name="onSuccess"></param>
        /// <returns></returns>
        public static string Move(UploadSuccess onSuccess = null)
        {
            string filename = ReqHelper.GetString("filename");
            string subfolder = ReqHelper.GetString("subfolder");
            return Move(filename, subfolder,true, onSuccess);
        }
        /// <summary>
        /// 获取移动之后的文件夹
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        public static string GetMoveName(string filename,string subFolder)
        {
            if (string.IsNullOrEmpty(filename))
                throw new Exception("获取移动后文件路径失败，filename为空");
            if(string.IsNullOrEmpty(subFolder))
                throw new Exception("获取移动后文件路径失败，subFolder");
            return subFolder + "/" + filename;
        }
        ///// <summary>
        ///// 文件名+相对目录
        ///// </summary>
        //public static string GetMoveName(string filename)
        //{
        //    string id = B_UserHelper.GetUserID().ToString();
        //    return id + "/" + filename;
        //}
        //public static string GetMoveName_A(string filename)
        //{
        //    string id = A_UserHelper.GetUserID().ToString();
        //    return id + "/" + filename;
        //}
        #endregion


        #region 消息内容输出
        /// <summary>
        /// 输出正确的描述
        /// </summary>
        /// <param name="str">消息内容</param>
        /// <returns></returns>
        public string GetSuccessStr(string str)
        {
            return "{'success':'1','msg':'" + str + "','oldname':'" + _fileInfo.OldName + "'}";
        }
        /// <summary>
        /// 输出报错时候的描述
        /// </summary>
        /// <param name="str">消息内容</param>
        /// <returns></returns>
        public string GetErrorStr(string str)
        {
            return "{'success':'0','msg':'" + str + "'}";
        }
        #endregion

    }
}